﻿using System.Diagnostics;
using System.Text;

namespace CmdApp
{
    internal class ConsoleColors : IDisposable
    {
        private static ConsoleColor _defaultForeground;

        public static void Initialize()
        {
            _defaultForeground = Console.ForegroundColor;
        }

        public ConsoleColors(ConsoleColor foreground)
        {
            Console.ForegroundColor = foreground;
        }

        public void Dispose()
        {
            Console.ForegroundColor = _defaultForeground;
        }
    }

    internal static class CommandsParser
    {
        public static IEnumerable<string> Parse(string commands)
        {
            StringBuilder cmd = new StringBuilder();
            for (int i = 0; i < commands.Length; ++i)
            {
                if (commands[i] == '&')
                {
                    yield return cmd.ToString().Trim();
                    cmd = new StringBuilder();
                }
                else if (commands[i] == '\"')
                {
                    cmd.Append(commands[i]);
                    ++i;
                    while (i < commands.Length && commands[i] != '\"')
                    {
                        cmd.Append(commands[i]);
                        ++i;
                    }
                    cmd.Append(commands[i]);
                }
                else
                {
                    cmd.Append(commands[i]);
                }
            }
            string strCmd = cmd.ToString().Trim();
            if (strCmd.Length != 0)
            {
                yield return strCmd;
            }
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            ConsoleColors.Initialize();
            const ConsoleColor pathInputColor = ConsoleColor.Cyan;
            const ConsoleColor inputColor = ConsoleColor.Yellow;
            const ConsoleColor errorColor = ConsoleColor.Red;
            string currentDirectory = Directory.GetCurrentDirectory();
            while (true)
            {
                using (new ConsoleColors(pathInputColor))
                {
                    Console.Write($"{currentDirectory}: ");
                }
                string commands;
                using (new ConsoleColors(inputColor))
                {
                    commands = Console.ReadLine().Trim();
                }
                foreach (string input in CommandsParser.Parse(commands))
                {
                    string command = input.Trim('"');
                    if (command.StartsWith("cd "))
                    {
                        string newPath = Path.GetFullPath(Path.Combine(currentDirectory, command.Substring(3).TrimStart().Trim('\"')));
                        if (!Directory.Exists(newPath))
                        {
                            using (new ConsoleColors(errorColor))
                            {
                                Console.WriteLine($"Директория {newPath} не существует!");
                            }
                            continue;
                        }
                        currentDirectory = newPath;
                        continue;
                    }
                    using (Process process = new Process())
                    {
                        ProcessStartInfo startInfo = new ProcessStartInfo()
                        {
                            WindowStyle = ProcessWindowStyle.Hidden,
                            FileName = "cmd.exe",
                            Arguments = $"/C {command}",
                            WorkingDirectory = currentDirectory,
                            UseShellExecute = false,
                            RedirectStandardOutput = true,
                            RedirectStandardError = true,
                            RedirectStandardInput = true
                        };
                        process.StartInfo = startInfo;
                        process.Start();

                        using (new ConsoleColors(errorColor))
                        {
                            while (!process.StandardError.EndOfStream)
                            {
                                string line = process.StandardError.ReadLine();
                                Console.WriteLine(line);
                            }
                        }

                        while (!process.StandardOutput.EndOfStream)
                        {
                            string line = process.StandardOutput.ReadLine();
                            Console.WriteLine(line);
                        }
                    }
                }
            }
        }
    }
}